"""
图片处理工具
"""
import os
import requests
from PIL import Image
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.conf import settings
from io import BytesIO
import sys


def validate_image(file):
    """
    验证图片文件
    :param file: 上传的文件对象
    :return: (is_valid, error_message)
    """
    # 检查文件扩展名
    ext = os.path.splitext(file.name)[1].lower()
    if ext not in settings.ALLOWED_IMAGE_EXTENSIONS:
        return False, f'不支持的文件格式。支持的格式：{", ".join(settings.ALLOWED_IMAGE_EXTENSIONS)}'
    
    # 检查文件大小
    if file.size > settings.MAX_IMAGE_SIZE:
        return False, f'文件大小超过限制（最大{settings.MAX_IMAGE_SIZE / 1024 / 1024}MB）'
    
    # 验证是否为有效图片
    try:
        img = Image.open(file)
        img.verify()
        file.seek(0)  # 重置文件指针
    except Exception as e:
        return False, f'无效的图片文件：{str(e)}'
    
    return True, None


def compress_image(image_file, max_size=(1920, 1920), quality=85, file_name=None):
    """
    压缩图片
    :param image_file: 图片文件对象（可以是文件对象或BytesIO）
    :param max_size: 最大尺寸 (width, height)
    :param quality: JPEG质量 (1-100)
    :param file_name: 文件名（可选，如果image_file没有name属性时使用）
    :return: 压缩后的文件对象
    """
    try:
        # 打开图片
        img = Image.open(image_file)
        
        # 转换为RGB模式（如果是RGBA或其他模式）
        if img.mode in ('RGBA', 'LA', 'P'):
            background = Image.new('RGB', img.size, (255, 255, 255))
            if img.mode == 'P':
                img = img.convert('RGBA')
            background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
            img = background
        elif img.mode != 'RGB':
            img = img.convert('RGB')
        
        # 调整尺寸
        img.thumbnail(max_size, Image.Resampling.LANCZOS)
        
        # 保存到内存
        output = BytesIO()
        img.save(output, format='JPEG', quality=quality, optimize=True)
        output.seek(0)
        
        # 创建新的文件对象
        # 优先使用传入的文件名，其次使用image_file.name，最后使用默认文件名
        if file_name:
            if not file_name.endswith('.jpg'):
                file_name = os.path.splitext(file_name)[0] + '.jpg'
        elif hasattr(image_file, 'name'):
            file_name = os.path.splitext(image_file.name)[0] + '.jpg'
        else:
            file_name = 'compressed_image.jpg'
        return InMemoryUploadedFile(
            output,
            'ImageField',
            file_name,
            'image/jpeg',
            sys.getsizeof(output),
            None
        )
    except Exception as e:
        raise ValueError(f'图片压缩失败：{str(e)}')


def generate_thumbnail(image_file, size=(300, 300)):
    """
    生成缩略图
    :param image_file: 图片文件对象
    :param size: 缩略图尺寸 (width, height)
    :return: 缩略图文件对象
    """
    try:
        img = Image.open(image_file)
        
        # 转换为RGB模式
        if img.mode in ('RGBA', 'LA', 'P'):
            background = Image.new('RGB', img.size, (255, 255, 255))
            if img.mode == 'P':
                img = img.convert('RGBA')
            background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
            img = background
        elif img.mode != 'RGB':
            img = img.convert('RGB')
        
        # 生成缩略图
        img.thumbnail(size, Image.Resampling.LANCZOS)
        
        # 保存到内存
        output = BytesIO()
        img.save(output, format='JPEG', quality=80, optimize=True)
        output.seek(0)
        
        # 创建新的文件对象
        file_name = os.path.splitext(image_file.name)[0] + '_thumb.jpg'
        return InMemoryUploadedFile(
            output,
            'ImageField',
            file_name,
            'image/jpeg',
            sys.getsizeof(output),
            None
        )
    except Exception as e:
        raise ValueError(f'缩略图生成失败：{str(e)}')


def download_image_from_url(image_url: str, timeout: int = 10) -> BytesIO:
    """
    从URL下载图片
    :param image_url: 图片URL
    :param timeout: 超时时间（秒）
    :return: 图片字节流
    """
    try:
        # 高德地图API的图片URL可能需要特殊处理
        # 如果URL包含高德地图的静态地图API，需要添加referer
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Referer': 'https://www.amap.com/'
        }
        
        # 如果是高德地图的静态地图URL，可能需要添加key参数
        if 'restapi.amap.com' in image_url and 'key=' not in image_url:
            # 尝试从settings获取API key
            try:
                from django.conf import settings
                api_key = settings.AMAP_CONFIG.get('API_KEY', '')
                if api_key:
                    separator = '&' if '?' in image_url else '?'
                    image_url = f"{image_url}{separator}key={api_key}"
            except:
                pass
        
        response = requests.get(image_url, headers=headers, timeout=timeout, stream=True, allow_redirects=True)
        response.raise_for_status()
        
        # 检查Content-Type是否为图片（某些服务器可能返回application/octet-stream）
        content_type = response.headers.get('Content-Type', '').lower()
        if content_type and not content_type.startswith('image/') and 'octet-stream' not in content_type:
            # 如果不是图片类型，检查文件大小和内容
            content_length = response.headers.get('Content-Length')
            if content_length and int(content_length) < 100:
                raise ValueError(f'URL返回的内容太小，可能不是图片: {content_type}')
        
        # 读取图片数据
        image_data = BytesIO()
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:
                image_data.write(chunk)
        image_data.seek(0)
        
        # 验证是否为有效图片
        try:
            img = Image.open(image_data)
            img.verify()
            image_data.seek(0)
        except Exception as e:
            # 如果验证失败，尝试重新打开
            image_data.seek(0)
            try:
                img = Image.open(image_data)
                # 尝试加载图片以确认它是有效的
                img.load()
                image_data.seek(0)
            except Exception as verify_error:
                raise ValueError(f'无效的图片文件: {str(verify_error)}')
        
        return image_data
    except requests.RequestException as e:
        raise ValueError(f'下载图片失败: {str(e)}')
    except Exception as e:
        raise ValueError(f'处理图片失败: {str(e)}')


def create_image_file_from_url(image_url: str, file_name: str = None) -> InMemoryUploadedFile:
    """
    从URL下载图片并创建文件对象
    :param image_url: 图片URL
    :param file_name: 文件名（可选）
    :return: Django文件对象
    """
    image_data = download_image_from_url(image_url)
    
    # 如果没有提供文件名，从URL中提取
    if not file_name:
        file_name = os.path.basename(image_url.split('?')[0])
        if not file_name or '.' not in file_name:
            file_name = 'image.jpg'
    
    # 确保文件名有扩展名
    if '.' not in file_name:
        file_name += '.jpg'
    
    # 压缩图片（传入文件名参数）
    image_data.seek(0)
    compressed_image = compress_image(image_data, max_size=(1920, 1920), quality=85, file_name=file_name)
    
    return compressed_image


